
#pragma once

#include "Sock.hpp"
#include <vector>
#include <functional>
#include <pthread.h>

namespace ns_tcpserver // 命名空间：
{
    class TcpServer; // 声明

    struct ThreadData
    {
        // 构造
        ThreadData(int sock, TcpServer *server)
            : sock_(sock), server_(server)
        {  }
        // 析构
        ~ThreadData()
        {  }

        int sock_;
        TcpServer *server_; // 为了直接传递this指针，方便回调函数调用整个类成员及函数
    };

    using func_t = std::function<void(int)>;

    // PS：这里使用的是多线程版本的服务端
    class TcpServer
    {
    private:
        static void *ThreadRoutine(void *args) // 类中成员函数：为了满足线程回调函数的参数需求，设置为静态成员函数
        {
            // 线程分离:为了服务端不阻塞式等待，需要对线程分离
            pthread_detach(pthread_self());
            // 解析args参数
            ThreadData *pdata = static_cast<ThreadData *>(args);

            // 调用任务处理函数
            pdata->server_->Excute(pdata->sock_);
            // 线程处理完任务后，需要关闭套接字，释放申请出来的空间
            logMessage(NORMAL,"新线程执行完毕，关闭套接字：%d",pdata->sock_);
            close(pdata->sock_);
            delete pdata;
            return nullptr;
        }

    public:
        // 构造：初始化服务器
        TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0")
        {
            // 创建套接字
            listensock_ = sock_.Socket();
            // 绑定套接字
            sock_.Bind(listensock_, port, ip);
            // 监听套接字
            sock_.Listen(listensock_);
        }

        // 析构
        ~TcpServer()
        {
            if (listensock_ >= 0)
                close(listensock_); // 关闭套接字
        }

        // 绑定服务:提供给TcpServer.cc，将服务器的业务处理函数插入到vector数组中
        void BindService(func_t func)
        {
            func_.push_back(func);
        }

        // 新线程执行业务处理函数
        void Excute(int sock)
        {
            for(auto& f : func_)
            {
                f(sock);
            }
        }


        // 启动服务器
        void Start()
        {
            // while死循环：服务器启动后，主线程一直在运行，不断接收客户端请求，并派发线程对其进行处理。
            while (true)
            {
                // 连接
                uint16_t client_port;                                                  // 客服端端口号
                std::string client_ip;                                                 // 客户端IP
                int servicesock = sock_.Accept(listensock_, &client_ip, &client_port); // 输出型参数，调用accept函数获取客户端的端口号和IP
                if (servicesock == -1)                                                 // 连接失败，重新连接
                    continue;
                logMessage(NORMAL, "连接成功, 可以开始业务处理。servicsock:%d", servicesock);

                // 派发新线程进行业务处理
                pthread_t tid;
                ThreadData *pdata = new ThreadData(servicesock, this);
                pthread_create(&tid, nullptr, ThreadRoutine, (void *)pdata);
            }
        }

    private:
        int listensock_;           // 套接字
        Sock sock_;                // 将套接字封装：用于调用相关socket函数
        std::vector<func_t> func_; // 服务端用于业务处理的函数：这里使用了vector将函数存储，表示服务器提供的处理业务可能有多种
    };
}